/*
* Application.java
*
* Copyright (C) 2009-17 by RStudio, Inc.
*
* Unless you have received this program directly from RStudio pursuant
* to the terms of a commercial license agreement with RStudio, then
* this program is licensed to you under the terms of version 3 of the
* GNU Affero General Public License. This program is distributed WITHOUT
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
* AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
*
*/
package org.rstudio.studio.client.application;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.RunAsyncCallback;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.FormElement;
import com.google.gwt.dom.client.InputElement;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import org.rstudio.core.client.Barrier;
import org.rstudio.core.client.BrowseCap;
import org.rstudio.core.client.Debug;
import org.rstudio.core.client.StringUtil;
import org.rstudio.core.client.Barrier.Token;
import org.rstudio.core.client.command.CommandBinder;
import org.rstudio.core.client.command.Handler;
import org.rstudio.core.client.dom.DocumentEx;
import org.rstudio.core.client.dom.DomUtils;
import org.rstudio.core.client.dom.WindowEx;
import org.rstudio.core.client.events.BarrierReleasedEvent;
import org.rstudio.core.client.events.BarrierReleasedHandler;
import org.rstudio.core.client.widget.Operation;
import org.rstudio.studio.client.application.ApplicationQuit.QuitContext;
import org.rstudio.studio.client.application.events.*;
import org.rstudio.studio.client.application.model.InvalidSessionInfo;
import org.rstudio.studio.client.application.model.ProductInfo;
import org.rstudio.studio.client.application.model.SessionSerializationAction;
import org.rstudio.studio.client.application.ui.AboutDialog;
import org.rstudio.studio.client.application.ui.RStudioThemes;
import org.rstudio.studio.client.application.ui.RequestLogVisualization;
import org.rstudio.studio.client.common.GlobalDisplay;
import org.rstudio.studio.client.common.SimpleRequestCallback;
import org.rstudio.studio.client.common.SuperDevMode;
import org.rstudio.studio.client.common.satellite.SatelliteManager;
import org.rstudio.studio.client.projects.Projects;
import org.rstudio.studio.client.projects.events.NewProjectEvent;
import org.rstudio.studio.client.projects.events.OpenProjectEvent;
import org.rstudio.studio.client.projects.events.SwitchToProjectEvent;
import org.rstudio.studio.client.server.*;
import org.rstudio.studio.client.workbench.ClientStateUpdater;
import org.rstudio.studio.client.workbench.Workbench;
import org.rstudio.studio.client.workbench.commands.Commands;
import org.rstudio.studio.client.workbench.events.LastChanceSaveEvent;
import org.rstudio.studio.client.workbench.events.SessionInitEvent;
import org.rstudio.studio.client.workbench.model.Agreement;
import org.rstudio.studio.client.workbench.model.Session;
import org.rstudio.studio.client.workbench.model.SessionInfo;
import org.rstudio.studio.client.workbench.model.SessionUtils;
import org.rstudio.studio.client.workbench.prefs.model.UIPrefs;
import org.rstudio.studio.client.workbench.views.source.editors.text.themes.AceThemes;
@Singleton
public class Application implements ApplicationEventHandlers
{
public interface Binder extends CommandBinder<Commands, Application> {}
@Inject
public Application(ApplicationView view,
GlobalDisplay globalDisplay,
EventBus events,
Binder binder,
Commands commands,
Server server,
Session session,
Projects projects,
SatelliteManager satelliteManager,
ApplicationUncaughtExceptionHandler uncaughtExHandler,
ApplicationTutorialApi tutorialApi,
MacZoomHandler zoomHandler,
Provider<UIPrefs> uiPrefs,
Provider<Workbench> workbench,
Provider<EventBus> eventBusProvider,
Provider<ClientStateUpdater> clientStateUpdater,
Provider<ApplicationClientInit> pClientInit,
Provider<ApplicationQuit> pApplicationQuit,
Provider<ApplicationInterrupt> pApplicationInterrupt,
Provider<AceThemes> pAceThemes)
{
// save references
view_ = view ;
globalDisplay_ = globalDisplay;
events_ = events;
session_ = session;
commands_ = commands;
satelliteManager_ = satelliteManager;
clientStateUpdater_ = clientStateUpdater;
server_ = server;
uiPrefs_ = uiPrefs;
workbench_ = workbench;
eventBusProvider_ = eventBusProvider;
pClientInit_ = pClientInit;
pApplicationQuit_ = pApplicationQuit;
pApplicationInterrupt_ = pApplicationInterrupt;
pAceThemes_ = pAceThemes;
// bind to commands
binder.bind(commands_, this);
// register as main window
satelliteManager.initialize();
// subscribe to events
events.addHandler(LogoutRequestedEvent.TYPE, this);
events.addHandler(UnauthorizedEvent.TYPE, this);
events.addHandler(ReloadEvent.TYPE, this);
events.addHandler(ReloadWithLastChanceSaveEvent.TYPE, this);
events.addHandler(QuitEvent.TYPE, this);
events.addHandler(SuicideEvent.TYPE, this);
events.addHandler(SessionAbendWarningEvent.TYPE, this);
events.addHandler(SessionSerializationEvent.TYPE, this);
events.addHandler(ServerUnavailableEvent.TYPE, this);
events.addHandler(InvalidClientVersionEvent.TYPE, this);
events.addHandler(ServerOfflineEvent.TYPE, this);
events.addHandler(InvalidSessionEvent.TYPE, this);
events.addHandler(SwitchToRVersionEvent.TYPE, this);
events.addHandler(ThemeChangedEvent.TYPE, this);
// register for uncaught exceptions
uncaughtExHandler.register();
}
public void go(final RootLayoutPanel rootPanel,
final Command dismissLoadingProgress)
{
rootPanel_ = rootPanel;
Widget w = view_.getWidget();
rootPanel.add(w);
rootPanel.setWidgetTopBottom(w, 0, Style.Unit.PX, 0, Style.Unit.PX);
rootPanel.setWidgetLeftRight(w, 0, Style.Unit.PX, 0, Style.Unit.PX);
// attempt init
pClientInit_.get().execute(
new ServerRequestCallback<SessionInfo>() {
public void onResponseReceived(final SessionInfo sessionInfo)
{
// initialize workbench after verifying agreement
verifyAgreement(sessionInfo, new Operation() {
public void execute()
{
// if this is a switch project then wait to dismiss the
// loading progress animation for 10 seconds. typically
// this will be enough time to switch projects. if it
// isn't then it's nice to reveal whatever progress
// operation or error state is holding up the switch
// directly to the user
if (ApplicationAction.isSwitchProject())
{
new Timer() {
@Override
public void run()
{
dismissLoadingProgress.execute();
}
}.schedule(10000);
}
else
{
dismissLoadingProgress.execute();
}
session_.setSessionInfo(sessionInfo);
// initialize workbench
initializeWorkbench();
}
});
}
public void onError(ServerError error)
{
Debug.logError(error);
dismissLoadingProgress.execute();
globalDisplay_.showErrorMessage("RStudio Initialization Error",
error.getUserMessage());
}
}) ;
}
@Handler
public void onShowToolbar()
{
setToolbarPref(true);
}
@Handler
public void onHideToolbar()
{
setToolbarPref(false);
}
@Handler
public void onToggleToolbar()
{
setToolbarPref(!view_.isToolbarShowing());
}
@Handler
void onShowAboutDialog()
{
server_.getProductInfo(new ServerRequestCallback<ProductInfo>()
{
@Override
public void onResponseReceived(ProductInfo info)
{
AboutDialog about = new AboutDialog(info);
about.showModal();
}
@Override
public void onError(ServerError error)
{
}
});
}
public void onUnauthorized(UnauthorizedEvent event)
{
navigateToSignIn();
}
public void onServerOffline(ServerOfflineEvent event)
{
cleanupWorkbench();
view_.showApplicationOffline();
}
public void onLogoutRequested(LogoutRequestedEvent event)
{
cleanupWorkbench();
// create an invisible form to host the sign-out process
FormElement form = DocumentEx.get().createFormElement();
form.setMethod("POST");
form.setAction(absoluteUrl("auth-sign-out", true));
form.getStyle().setDisplay(Display.NONE);
// read the CSRF token from the cookie and place it in the form
InputElement csrfToken = DocumentEx.get().createHiddenInputElement();
csrfToken.setName(CSRF_TOKEN_FIELD);
csrfToken.setValue(Cookies.getCookie(CSRF_TOKEN_FIELD));
form.appendChild(csrfToken);
// append the form to the document and submit it
DocumentEx.get().getBody().appendChild(form);
form.submit();
}
@Handler
public void onHelpUsingRStudio()
{
String customDocsURL = session_.getSessionInfo().docsURL();
if (customDocsURL.length() > 0)
globalDisplay_.openWindow(customDocsURL);
else
globalDisplay_.openRStudioLink("docs");
}
private void showAgreement()
{
globalDisplay_.openWindow(server_.getApplicationURL("agreement"));
}
@Handler
public void onRstudioSupport()
{
globalDisplay_.openRStudioLink("support");
}
@Handler
public void onRstudioAgreement()
{
showAgreement();
}
@Handler
public void onUpdateCredentials()
{
server_.updateCredentials();
}
@Handler
public void onRaiseException() {
throw new RuntimeException("foo");
}
@Handler
public final native void onRaiseException2() /*-{
$wnd.welfkjweg();
}-*/;
@Handler
public void onShowRequestLog()
{
GWT.runAsync(new RunAsyncCallback()
{
public void onFailure(Throwable reason)
{
Window.alert(reason.toString());
}
public void onSuccess()
{
final RequestLogVisualization viz = new RequestLogVisualization();
final RootLayoutPanel root = RootLayoutPanel.get();
root.add(viz);
root.setWidgetTopBottom(viz, 10, Unit.PX, 10, Unit.PX);
root.setWidgetLeftRight(viz, 10, Unit.PX, 10, Unit.PX);
viz.addCloseHandler(new CloseHandler<RequestLogVisualization>()
{
public void onClose(CloseEvent<RequestLogVisualization> event)
{
root.remove(viz);
}
});
}
});
}
@Handler
public void onLogFocusedElement()
{
Element el = DomUtils.getActiveElement();
DomUtils.dump(el, "Focused Element: ");
}
@Handler
public void onRefreshSuperDevMode()
{
SuperDevMode.reload();
}
public void onSessionSerialization(SessionSerializationEvent event)
{
switch(event.getAction().getType())
{
case SessionSerializationAction.LOAD_DEFAULT_WORKSPACE:
view_.showSerializationProgress(
"Loading workspace" + getSuffix(event),
false, // non-modal, appears to user as std latency
500, // willing to show progress earlier since
// this will always be at workbench startup
0); // no timeout
break;
case SessionSerializationAction.SAVE_DEFAULT_WORKSPACE:
view_.showSerializationProgress(
"Saving workspace image" + getSuffix(event),
true, // modal, inputs will fall dead anyway
0, // show immediately
0); // no timeout
break;
case SessionSerializationAction.SUSPEND_SESSION:
view_.showSerializationProgress(
"Backing up R session...",
true, // modal, inputs will fall dead anyway
0, // show immediately
60000); // timeout after 60 seconds. this is done
// in case the user suspends or loses
// connectivity during the backup (in which
// case the 'completed' event dies with
// server and is never received by the client
break;
case SessionSerializationAction.RESUME_SESSION:
view_.showSerializationProgress(
"Resuming R session...",
false, // non-modal, appears to user as std latency
2000, // don't show this for reasonable restore time
// (happens inline while using a running
// workbench so be more conservative)
0); // no timeout
break;
case SessionSerializationAction.COMPLETED:
view_.hideSerializationProgress();
break;
}
}
private String getSuffix(SessionSerializationEvent event)
{
SessionSerializationAction action = event.getAction();
String targetPath = action.getTargetPath();
if (targetPath != null)
{
String verb = " from ";
if (action.getType() == SessionSerializationAction.SAVE_DEFAULT_WORKSPACE)
verb = " to ";
return verb + targetPath + "...";
}
else
{
return "...";
}
}
public void onServerUnavailable(ServerUnavailableEvent event)
{
view_.hideSerializationProgress();
}
@Override
public void onSwitchToRVersion(final SwitchToRVersionEvent event)
{
final ApplicationQuit applicaitonQuit = pApplicationQuit_.get();
applicaitonQuit.prepareForQuit("Switch R Version",
new QuitContext() {
public void onReadyToQuit(boolean saveChanges)
{
// see if we have a project (otherwise switch to "None")
String project = session_.getSessionInfo().getActiveProjectFile();
if (project == null)
project = Projects.NONE;
// do the quit
applicaitonQuit.performQuit(saveChanges,
project,
event.getRVersionSpec());
}
});
}
public void onReload(ReloadEvent event)
{
cleanupWorkbench();
reloadWindowWithDelay(false);
}
public void onReloadWithLastChanceSave(ReloadWithLastChanceSaveEvent event)
{
Barrier barrier = new Barrier();
barrier.addBarrierReleasedHandler(new BarrierReleasedHandler() {
@Override
public void onBarrierReleased(BarrierReleasedEvent event)
{
events_.fireEvent(new ReloadEvent());
}
});
Token token = barrier.acquire();
try
{
events_.fireEvent(new LastChanceSaveEvent(barrier));
}
finally
{
token.release();
}
}
public void onQuit(QuitEvent event)
{
cleanupWorkbench();
// only show the quit state in server mode (desktop mode has its
// own handling triggered to process exit)
if (!Desktop.isDesktop())
{
// if we are switching projects then reload after a delay (to allow
// the R session to fully exit on the server)
if (event.getSwitchProjects())
{
String nextSessionUrl = event.getNextSessionUrl();
if (!StringUtil.isNullOrEmpty(nextSessionUrl))
{
// forward any query string parameters (e.g. the edit_published
// parameter might follow an action=switch_project)
String query = ApplicationAction.getQueryStringWithoutAction();
if (query.length() > 0)
nextSessionUrl = nextSessionUrl + "?" + query;
navigateWindowWithDelay(nextSessionUrl);
}
else
{
reloadWindowWithDelay(true);
}
}
else
{
if (session_.getSessionInfo().getMultiSession())
{
view_.showApplicationMultiSessionQuit();
}
else
{
view_.showApplicationQuit();
}
// attempt to close the window if this is a quit
// action (may or may not be able to depending on
// how it was created)
if (ApplicationAction.isQuit() && !ApplicationAction.isQuitToHome())
{
try
{
WindowEx.get().close();
}
catch(Exception ex)
{
}
}
else if (session_.getSessionInfo().getShowUserHomePage())
{
navigateWindowWithDelay(
session_.getSessionInfo().getUserHomePageUrl());
}
}
}
}
private void reloadWindowWithDelay(final boolean baseUrlOnly)
{
new Timer() {
@Override
public void run()
{
if (baseUrlOnly)
Window.Location.replace(GWT.getHostPageBaseURL());
else
Window.Location.reload();
}
}.schedule(100);
}
private void navigateWindowWithDelay(final String url)
{
new Timer() {
@Override
public void run()
{
Window.Location.replace(url);
}
}.schedule(100);
}
public void onSuicide(SuicideEvent event)
{
cleanupWorkbench();
view_.showApplicationSuicide(event.getMessage());
}
public void onClientDisconnected(ClientDisconnectedEvent event)
{
cleanupWorkbench();
view_.showApplicationDisconnected();
}
public void onInvalidClientVersion(InvalidClientVersionEvent event)
{
cleanupWorkbench();
view_.showApplicationUpdateRequired();
}
public void onInvalidSession(InvalidSessionEvent event)
{
// calculate the url without the scope
InvalidSessionInfo info = event.getInfo();
String baseURL = GWT.getHostPageBaseURL();
String scopePath = info.getScopePath();
int loc = baseURL.indexOf(scopePath);
if (loc != -1)
baseURL = baseURL.substring(0, loc) + "/";
if (info.getScopeState() == InvalidSessionInfo.ScopeMissingProject)
{
baseURL += "projectnotfound.htm";
}
else
{
// add the scope info to the query string
baseURL += "?project="
+ URL.encodeQueryString(info.getSessionProject()) + "&id="
+ URL.encodeQueryString(info.getSessionProjectId());
}
navigateWindowWithDelay(baseURL);
}
public void onSessionAbendWarning(SessionAbendWarningEvent event)
{
view_.showSessionAbendWarning();
}
@Override
public void onThemeChanged(ThemeChangedEvent event)
{
RStudioThemes.initializeThemes(uiPrefs_.get().getFlatTheme().getGlobalValue(),
Document.get(),
rootPanel_.getElement());
}
private void verifyAgreement(SessionInfo sessionInfo,
final Operation verifiedOperation)
{
// get the agreement (if any)
final Agreement agreement = sessionInfo.pendingAgreement();
// if there is an agreement then prompt user for agreement (otherwise just
// execute the verifiedOperation immediately)
if (agreement != null)
{
// append updated to the title if necessary
String title = agreement.getTitle();
if (agreement.getUpdated())
title += " (Updated)";
view_.showApplicationAgreement(
// title and contents
title,
agreement.getContents(),
// bail to sign in page if the user doesn't confirm
new Operation()
{
public void execute()
{
if (Desktop.isDesktop())
{
Desktop.getFrame().setPendingQuit(
DesktopFrame.PENDING_QUIT_AND_EXIT);
server_.quitSession(false,
null,
null,
GWT.getHostPageBaseURL(),
new SimpleRequestCallback<Boolean>());
}
else
navigateToSignIn();
}
},
// user confirmed
new Operation() {
public void execute()
{
// call verified operation
verifiedOperation.execute();
// record agreement on server
server_.acceptAgreement(agreement,
new VoidServerRequestCallback());
}
}
);
}
else
{
// no agreement pending
verifiedOperation.execute();
}
}
private void navigateWindowTo(String relativeUrl)
{
navigateWindowTo(relativeUrl, true);
}
private void navigateWindowTo(String relativeUrl, boolean includeContext)
{
cleanupWorkbench();
// navigate window
Window.Location.replace(absoluteUrl(relativeUrl, includeContext));
}
private String absoluteUrl(String relativeUrl, boolean includeContext)
{
// ensure there is no session context if requested
String url = includeContext ?
GWT.getHostPageBaseURL() :
ApplicationUtils.getHostPageBaseURLWithoutContext(true);
// add relative URL
url += relativeUrl;
return url;
}
private void initializeWorkbench()
{
RStudioThemes.initializeThemes(uiPrefs_.get().getFlatTheme().getGlobalValue(),
Document.get(),
rootPanel_.getElement());
pAceThemes_.get();
// subscribe to ClientDisconnected event (wait to do this until here
// because there were spurious ClientDisconnected events occuring
// after a session interrupt sequence. we couldn't figure out why,
// and since this is a temporary hack why not add another temporary
// hack to go with it here :-)
// TOOD: move this back tot he constructor after we revise the
// interrupt hack(s)
events_.addHandler(ClientDisconnectedEvent.TYPE, this);
// create workbench
Workbench wb = workbench_.get();
eventBusProvider_.get().fireEvent(new SessionInitEvent()) ;
// disable commands
SessionInfo sessionInfo = session_.getSessionInfo();
if (!sessionInfo.getAllowShell())
{
commands_.showShellDialog().remove();
removeTerminalCommands();
}
if (!sessionInfo.getAllowPackageInstallation())
{
commands_.installPackage().remove();
commands_.updatePackages().remove();
}
if (!sessionInfo.getAllowVcs())
{
commands_.versionControlProjectSetup().remove();
}
if (!sessionInfo.getAllowFileDownloads())
{
commands_.exportFiles().remove();
}
if (!sessionInfo.getAllowFileUploads())
{
commands_.uploadFile().remove();
}
// disable external publishing if requested
if (!SessionUtils.showExternalPublishUi(session_, uiPrefs_.get()))
{
commands_.publishHTML().remove();
}
// hide the agreement menu item if we don't have one
if (!session_.getSessionInfo().hasAgreement())
commands_.rstudioAgreement().setVisible(false);
// remove knit params if they aren't supported
if (!sessionInfo.getKnitParamsAvailable())
commands_.knitWithParameters().remove();
// show the correct set of data import commands
if (uiPrefs_.get().useDataImport().getValue())
{
commands_.importDatasetFromFile().remove();
commands_.importDatasetFromURL().remove();
commands_.importDatasetFromCsvUsingReadr().setVisible(false);
commands_.importDatasetFromSAV().setVisible(false);
commands_.importDatasetFromSAS().setVisible(false);
commands_.importDatasetFromStata().setVisible(false);
commands_.importDatasetFromXML().setVisible(false);
commands_.importDatasetFromODBC().setVisible(false);
commands_.importDatasetFromJDBC().setVisible(false);
try
{
String rVersion = sessionInfo.getRVersionsInfo().getRVersion();
if (ApplicationUtils.compareVersions(rVersion, "3.0.2") >= 0)
{
commands_.importDatasetFromCsvUsingReadr().setVisible(true);
}
if (ApplicationUtils.compareVersions(rVersion, "3.1.0") >= 0)
{
commands_.importDatasetFromSAV().setVisible(true);
commands_.importDatasetFromSAS().setVisible(true);
commands_.importDatasetFromStata().setVisible(true);
commands_.importDatasetFromXML().setVisible(true);
}
if (ApplicationUtils.compareVersions(rVersion, "3.0.0") >= 0)
{
commands_.importDatasetFromODBC().setVisible(true);
}
if (ApplicationUtils.compareVersions(rVersion, "2.4.0") >= 0)
{
commands_.importDatasetFromJDBC().setVisible(true);
}
}
catch (Exception e)
{
}
// Removing data import dialogs that are NYI
commands_.importDatasetFromXML().remove();
commands_.importDatasetFromJSON().remove();
commands_.importDatasetFromJDBC().remove();
commands_.importDatasetFromODBC().remove();
commands_.importDatasetFromMongo().remove();
}
else
{
commands_.importDatasetFromCsv().remove();
commands_.importDatasetFromCsvUsingBase().remove();
commands_.importDatasetFromCsvUsingReadr().remove();
commands_.importDatasetFromSAV().remove();
commands_.importDatasetFromSAS().remove();
commands_.importDatasetFromStata().remove();
commands_.importDatasetFromXLS().remove();
commands_.importDatasetFromXML().remove();
commands_.importDatasetFromJSON().remove();
commands_.importDatasetFromJDBC().remove();
commands_.importDatasetFromODBC().remove();
commands_.importDatasetFromMongo().remove();
}
// show workbench
view_.showWorkbenchView(wb.getMainView().asWidget());
// hide zoom actual size everywhere but cocoa desktop
if (!BrowseCap.isCocoaDesktop())
{
commands_.zoomActualSize().remove();
}
// hide zoom in and zoom out in web mode
if (!Desktop.isDesktop())
{
commands_.zoomIn().remove();
commands_.zoomOut().remove();
}
// show new session when appropriate
if (!Desktop.isDesktop())
{
if (sessionInfo.getMultiSession())
commands_.newSession().setMenuLabel("New Session...");
else
commands_.newSession().remove();
}
// toolbar (must be after call to showWorkbenchView because
// showing the toolbar repositions the workbench view widget)
showToolbar( uiPrefs_.get().toolbarVisible().getValue());
// sync to changes in the toolbar visibility state
uiPrefs_.get().toolbarVisible().addValueChangeHandler(
new ValueChangeHandler<Boolean>() {
@Override
public void onValueChange(ValueChangeEvent<Boolean> event)
{
showToolbar(event.getValue());
}
});
clientStateUpdaterInstance_ = clientStateUpdater_.get();
// initiate action if requested. do this after a delay
// so that the source database has time to load
// before we interrogate it for unsaved documents
if (ApplicationAction.hasAction())
{
new Timer() {
@Override
public void run() {
if (ApplicationAction.isQuit())
{
commands_.quitSession().execute();
}
else if (ApplicationAction.isNewProject())
{
ApplicationAction.removeActionFromUrl();
events_.fireEvent(new NewProjectEvent(true, false));
}
else if (ApplicationAction.isOpenProject())
{
ApplicationAction.removeActionFromUrl();
events_.fireEvent(new OpenProjectEvent(true, false));
}
else if (ApplicationAction.isSwitchProject())
{
handleSwitchProjectAction();
}
}
}.schedule(500);
}
}
private void handleSwitchProjectAction()
{
String projectId = ApplicationAction.getId();
if (projectId.length() > 0)
{
server_.getProjectFilePath(
projectId,
new ServerRequestCallback<String>() {
@Override
public void onResponseReceived(String projectFilePath)
{
if (projectFilePath.length() > 0)
{
events_.fireEvent(
new SwitchToProjectEvent(projectFilePath, true));
}
}
@Override
public void onError(ServerError error)
{
Debug.logError(error);
}
});
}
}
private void setToolbarPref(boolean showToolbar)
{
uiPrefs_.get().toolbarVisible().setGlobalValue(showToolbar);
uiPrefs_.get().writeUIPrefs();
}
private void showToolbar(boolean showToolbar)
{
// show or hide the toolbar
view_.showToolbar(showToolbar);
// manage commands
commands_.showToolbar().setVisible(!showToolbar);
commands_.hideToolbar().setVisible(showToolbar);
}
private void cleanupWorkbench()
{
server_.disconnect();
satelliteManager_.closeAllSatellites();
if (clientStateUpdaterInstance_ != null)
{
clientStateUpdaterInstance_.suspend();
clientStateUpdaterInstance_ = null;
}
}
private void navigateToSignIn()
{
navigateWindowTo("auth-sign-in");
}
private void removeTerminalCommands()
{
commands_.newTerminal().remove();
commands_.activateTerminal().remove();
commands_.renameTerminal().remove();
commands_.closeTerminal().remove();
commands_.clearTerminalScrollbackBuffer().remove();
commands_.previousTerminal().remove();
commands_.nextTerminal().remove();
commands_.showTerminalInfo().remove();
}
private final ApplicationView view_ ;
private final GlobalDisplay globalDisplay_ ;
private final EventBus events_;
private final Session session_;
private final Commands commands_;
private final SatelliteManager satelliteManager_;
private final Provider<ClientStateUpdater> clientStateUpdater_;
private final Server server_;
private final Provider<UIPrefs> uiPrefs_;
private final Provider<Workbench> workbench_;
private final Provider<EventBus> eventBusProvider_;
private final Provider<ApplicationClientInit> pClientInit_;
private final Provider<ApplicationQuit> pApplicationQuit_;
private final Provider<ApplicationInterrupt> pApplicationInterrupt_;
private final Provider<AceThemes> pAceThemes_;
private final String CSRF_TOKEN_FIELD = "csrf-token";
private ClientStateUpdater clientStateUpdaterInstance_;
private RootLayoutPanel rootPanel_;
}